// **************************************************************
// COPYRIGHT(c)2020, Xidian University
// All rights reserved.
//
// IP LIB INDEX :  
// IP Name      :      
// File name    : axis_data_fifo.v
// Module name  : axis_data_fifo
// Full name    :  
//
// Author       : lhb
// Email        : 2296971136@qq.com
// Data         : 2021/4/27
// Version      : V 1.0 
// 
// Abstract     : Packet Mode    synchronous clock      4clk from in to out
// Called by    :  
// 
// Modification history
// -----------------------------------------------------------------
// 
// 
// 
// *****************************************************************
`include "top_define.v"
module axis_data_fifo(
    input wire  [9:0]   ram_2p_cfg_register,
    input wire              s_axis_aresetn      ,
    input wire              s_axis_aclk         ,
    input wire              s_axis_tvalid       ,
    output wire             s_axis_tready       ,
    input wire [255 : 0]    s_axis_tdata        ,
    input wire [31 : 0]     s_axis_tkeep        ,
    input wire              s_axis_tlast        ,
    // input wire [0 : 0]      s_axis_tuser        ,

    output reg             m_axis_tvalid       ,
    input wire             m_axis_tready       ,
    output reg [255 : 0]   m_axis_tdata        ,
    output reg [31 : 0]    m_axis_tkeep        ,
    output reg             m_axis_tlast        
    // output reg [0 : 0]     m_axis_tuser        
    // output reg [31 : 0]    axis_data_count     ,
    // output reg [31 : 0]    axis_wr_data_count  ,
    // output reg [31 : 0]    axis_rd_data_count
);

wire fifo_we;
wire [288:0] fifo_data_i;
reg fifo_rd_temp;
reg [6:0] pkt_cnt;

wire fifo_rd;
wire [288:0] fifo_data_o;
wire fifo_full;
wire fifo_empty;
wire prog_full;

// //\u5199\u4f7f\u80fd
// always @(posedge s_axis_aclk or negedge s_axis_aresetn) begin
//     if (!s_axis_aresetn) begin
//         fifo_we <= 1'b0;
//     end
//     else if (s_axis_tready && s_axis_tvalid && !fifo_full) begin
//         fifo_we <= 1'b1;
//     end
//     else begin
//         fifo_we <= 1'b0;
//     end
// end
assign fifo_we = s_axis_tready && s_axis_tvalid && !fifo_full;

assign fifo_data_i = s_axis_tvalid ? {s_axis_tlast,s_axis_tkeep,s_axis_tdata} : 289'b0;

//fifo_data_i
// _ _ _ 1 _ _ _ _ _ _32_ _ _ _ _ _ _ 256 _ _ _
//|     288    |    287~256    |     255~0     |
//|___ last  __|___  tkeep  ___|___  tdata  ___|
// always @(posedge s_axis_aclk or negedge s_axis_aresetn) begin
//     if (!s_axis_aresetn) begin
//         fifo_data_i <= 289'b0;
//     end
//     else if (s_axis_tvalid) begin
//         fifo_data_i <= {s_axis_tlast,s_axis_tkeep,s_axis_tdata};
//     end
//     else begin
//         fifo_data_i <= 289'b0;
//     end
// end

//\u8bfb\u4f7f\u80fd
//  \u8bfb\u51fa\u5e27\u5c3e,\u8bfb\u4f7f\u80fd\u7f6e0
//  TLAST\u4fe1\u53f7\u88ab\u54cd\u5e94\uff08\u6709\u5305\uff09\u6216\u8005FIFO\u6ee1,\u8bfb\u4f7f\u80fd\u7f6e1
always @(posedge s_axis_aclk or negedge s_axis_aresetn) begin
	if (!s_axis_aresetn) begin
		fifo_rd_temp <= 1'b0;
	end
	else if (fifo_data_o[288] && fifo_rd) begin 
		fifo_rd_temp <= 1'b0;
	end
	else if ((|pkt_cnt) /* || fifo_full  */) begin
		fifo_rd_temp <= 1'b1;
	end
	else begin
		fifo_rd_temp <= 1'b0;
	end
end

assign fifo_rd = fifo_rd_temp && m_axis_tready;

//\u5305\u8ba1\u6570
//  FIFO\u5199\u5165\u5e27\u5c3e\uff0c\u8bfb\u51fa\u5e27\u5c3e,\u4e0d\u53d8
//  FIFO\u5199\u5165\u5e27\u5c3e,\u9012\u589e
//  FIFO\u8bfb\u51fa\u5e27\u5c3e,\u9012\u51cf
always @(posedge s_axis_aclk or negedge s_axis_aresetn) begin
	if (!s_axis_aresetn) begin
		pkt_cnt <= 7'b0;
	end
	else if (fifo_data_i[288] && fifo_we && fifo_data_o[288] && fifo_rd) begin
		pkt_cnt <= pkt_cnt;
	end
	else if (fifo_data_i[288] && fifo_we) begin
		pkt_cnt <= pkt_cnt + 7'b1;
	end
	else if (fifo_data_o[288] && fifo_rd) begin
		pkt_cnt <= pkt_cnt - 7'b1;
	end
	else begin
		pkt_cnt <= pkt_cnt;
	end
end

//axi_stream out
always @(posedge s_axis_aclk or negedge s_axis_aresetn) begin
    if (!s_axis_aresetn) begin
        m_axis_tvalid   <= 1'b0;
        m_axis_tdata    <= 256'b0;
        m_axis_tkeep    <= 32'b0;
        m_axis_tlast    <= 1'b0;
        // m_axis_tuser    <= 1'b0;
    end
    else if (!m_axis_tready) begin
        m_axis_tvalid   <= m_axis_tvalid;
        m_axis_tdata    <= m_axis_tdata ;
        m_axis_tkeep    <= m_axis_tkeep ;
        m_axis_tlast    <= m_axis_tlast ;
        // m_axis_tuser    <= 1'b0 ;
    end
    else if (fifo_rd) begin
        m_axis_tvalid   <= 1'b1;
        m_axis_tdata    <= fifo_data_o[255:0] ;
        m_axis_tkeep    <= fifo_data_o[287:256] ;
        m_axis_tlast    <= fifo_data_o[288] ;
        // m_axis_tuser    <= 1'b0 ;
    end
    else begin
        m_axis_tvalid   <= 1'b0;
        m_axis_tdata    <= 256'b0;
        m_axis_tkeep    <= 32'b0;
        m_axis_tlast    <= 1'b0;
        // m_axis_tuser    <= 1'b0;
    end
end

//\u6570\u636e\u8ba1\u6570
//  \u8f93\u5165\u6570\u636e\u6709\u6548\u9012\u589e
//  \u8f93\u51fa\u6570\u636e\u6709\u6548\u9012\u51cf
// always @(posedge s_axis_aclk or negedge s_axis_aresetn) begin
//     if (!s_axis_aresetn) begin
//         axis_data_count <= 32'b0;
//     end
//     else if (m_axis_tvalid && s_axis_tready && s_axis_tvalid && !fifo_full) begin
//         axis_data_count <= axis_data_count;
//     end
//     else if (s_axis_tready && s_axis_tvalid && !fifo_full) begin
//         axis_data_count <= axis_data_count + 32'b1;
//     end
//     else if (m_axis_tvalid) begin
//         axis_data_count <= axis_data_count - 32'b1;
//     end
//     else begin
//         axis_data_count <= axis_data_count;
//     end
// end


//ASIC_MODE
// Instance of DW_fifo_s1_sf
`ifdef ASIC
syn_fwft_fifo_d256_w289 #(
    .L(8),   
    .DW(289) 
)
U_syn_fwft_fifo_d256_w289(
    .clk(s_axis_aclk),
    .clr(s_axis_aresetn),
    .ram_2p_cfg_register(ram_2p_cfg_register),
    .w_data(fifo_data_i),
    .w_we(fifo_we),
    .w_full(fifo_full),
    .w_afull(prog_full),

    .r_data(fifo_data_o),
    .r_re(fifo_rd),
    .r_empty(fifo_empty),
    .r_aempty()
);

`else
syn_fwft_fifo U_syn_fwft_fifo(
  .clk(s_axis_aclk),              // input wire clk
  .rst(!s_axis_aresetn),        // input wire rst
  .din(fifo_data_i),        // input wire [288 : 0] din
  .wr_en(fifo_we),    // input wire wr_en
  .rd_en(fifo_rd),    // input wire rd_en
  .dout(fifo_data_o),      // output wire [288 : 0] dout
  .full(fifo_full),      // output wire full
  .empty(fifo_empty),    // output wire empty
  .prog_full(prog_full)  // output wire prog_full
);
`endif


//prog_full\u8bbe\u7f6e(\u6df1\u5ea6-47\uff0c\u4e00\u4e2a\u6700\u957f\u5e27)
assign s_axis_tready = ~prog_full;

endmodule
